﻿// ChatWin.cpp: 实现文件
//

#include "pch.h"
#include "ChatSystem.h"
#include "afxdialogex.h"
#include "ChatWin.h"
#include "ChatMsg.h"
#include "TcpSvr.h"
#include "MsgQueue.h"
#include <string.h>
#include "CDialogAddFriend.h"

// ChatWin 对话框

IMPLEMENT_DYNAMIC(ChatWin, CDialogEx)

ChatWin::ChatWin(int userid, CWnd* pParent /*=nullptr*/)
	:uid_(userid)
	,CDialogEx(IDD_CHATWIN, pParent)
	, user_input_(_T(""))
{

}

ChatWin::~ChatWin()
{
}

void ChatWin::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_LISTFRIENDINFO, friend_list);
	DDX_Control(pDX, IDC_LISTMSGINFO, msg_list_);
	DDX_Text(pDX, IDC_EDIT1, user_input_);
	DDX_Control(pDX, IDC_EDIT1, user_input_edit_);
}


BEGIN_MESSAGE_MAP(ChatWin, CDialogEx)
	
	ON_BN_CLICKED(IDC_BUTSENDMSG, &ChatWin::OnBnClickedButsendmsg)
	ON_LBN_SELCHANGE(IDC_LISTFRIENDINFO, &ChatWin::OnLbnSelchangeListfriendinfo)
	ON_LBN_SELCHANGE(IDC_LISTMSGINFO, &ChatWin::OnLbnSelchangeListmsginfo)
	ON_BN_CLICKED(ID_ADDFRIEND, &ChatWin::OnBnClickedAddfriend)
END_MESSAGE_MAP()


// ChatWin 消息处理程序


//void ChatWin::OnBnClickedButton2()
//{
//	// TODO: 在此添加控件通知处理程序代码
//}


void ChatWin::OnBnClickedButsendmsg()
{
	// TODO: 在此添加控件通知处理程序代码
	//1.获取聊天框的内容
	UpdateData(TRUE);
	if (user_input_.IsEmpty()) {
		MessageBox("输入内容不能为空");
		return;
	}
	//2.获取tcp实例化指针
	TcpSvr* ts = TcpSvr::GetInstance();
	if (ts == NULL) {
		MessageBox("获取TCP指针失败,请过一会儿再试");
		return;
	}

	//3.组织消息并发送
	ChatMsg cm;
	cm.msg_type_ = SendMsg;
	cm.userid_ = uid_;
	cm.json_msg_["recvmsgid"] = suid_;
	cm.json_msg_["mag"] = user_input_.GetString();

	std::string msg;
	cm.GetMsg(&msg);

	ts->Send(msg);

	//4.接收应答,判断消息是否发送成功
	MsgQueue* mq = MsgQueue::GetInstance();
	msg.clear();
	cm.clear();
	mq->Pop(SendMsg_Resp, &msg);
	cm.PraseChatMsg(-1, msg);

	//5.结果展示到编辑框
	for (int i = 0; i < vec_fri_.size(); i++) {
		if (suid_ == vec_fri_[i].userid_) {
			std::string show_msg = "我: ";
			show_msg += user_input_.GetString();
			if (cm.reply_status_ == SENDMSG_SUCCESS) {
				show_msg += " (Y)";
			}
			else {
				show_msg += " (N)";
			}
			vec_fri_[i].history_msg_.push_back(show_msg);
			msg_list_.AddString(show_msg.c_str());
		}
	}

	//6.清空控件
	user_input_.Empty();
	user_input_edit_.SetWindowTextA(0);

}

void DealPushMsg(ChatWin* cw) {
	MsgQueue* mq = MsgQueue::GetInstance();
	while (1) {
		std::string msg;
		mq->Pop(PushMsg , &msg);

		ChatMsg cm;
		cm.PraseChatMsg(-1, msg);

		std::string peer_nickname = cm.json_msg_["peer_nickname"].asString();
		std::string peer_school = cm.json_msg_["peer_school"].asString();
		std::string peer_msg = cm.json_msg_["peer_msg"].asString();
		int peer_id = cm.json_msg_["peer_user_id"].asInt();
		for (int i = 0; i < cw->vec_fri_.size(); i++) {
			if (peer_id == cw->vec_fri_[i].userid_) {
				std::string temp = peer_nickname + "-" + peer_school + ": " + peer_msg;
				cw->vec_fri_[i].history_msg_.push_back(temp);
				if (peer_id == cw->suid_) {
					cw->msg_list_.AddString(temp.c_str());
				}
				else {
					cw->vec_fri_[i].msg_cnt_++;

				}
			}
		}
		cw->RefreshUserList();
	}
}


void DealAddFriendMsg(ChatWin* cw) {
	MsgQueue* mq = MsgQueue::GetInstance();
	while (1) {
		std::string msg;
		mq->Pop(PushAddFriendMsg , &msg);
		ChatMsg cm;
		cm.PraseChatMsg(-1, msg);

		std::string adder_nickname = cm.json_msg_["adder_nickname"].asString();
		std::string adder_school = cm.json_msg_["adder_school"].asString();
		int adder_userid = cm.json_msg_["adder_userid"].asInt();
		
		std::string show_info = adder_nickname + "(" + adder_school + ")" "want to add you be a friend ^-^";
		int i = MessageBox(cw->m_hWnd, show_info.c_str(), "好友请求", MB_YESNO);
		if (i == IDYES) {
			//刷新好友信息
			struct UserInfo ui;
			ui.nickname_ = adder_nickname;
			ui.school_ = adder_school;
			ui.userid_ = adder_userid;
			ui.msg_cnt_ = 0;
			cw->vec_fri_.push_back(ui);
			//刷新展示区域
			cw->RefreshUserList();
			//组织应答
			cm.clear();
			cm.msg_type_ = PushAddFriendMsg_Resp;
			cm.reply_status_ = ADDFRIEND_SUCCESS;
			cm.userid_ = cw->uid_;
			cm.json_msg_["userid"] = adder_userid;
		}
		else {
			cm.clear();
			cm.msg_type_ = PushAddFriendMsg_Resp;
			cm.reply_status_ = ADDFRIEND_FAILED;
			cm.userid_ = cw->uid_;
			cm.json_msg_["userid"] = adder_userid;
		}
		msg.clear();
		cm.GetMsg(&msg);
		TcpSvr* ts = TcpSvr::GetInstance();
		ts->Send(msg);
	}
}

void DealAddFriendRespMsg(ChatWin* cw) {
	MsgQueue* mq = MsgQueue::GetInstance();
	while (1) {
		std::string msg;
		mq->Pop(PushAddFriendMsg, &msg);
		ChatMsg cm;
		cm.PraseChatMsg(-1, msg);

		std::string connect = cm.GetValue("connect");
		MessageBox(cw->m_hWnd, connect.c_str(), "请求结果", MB_OK);

		std::string be_adder_nickname = cm.json_msg_["peer_nick_name"].asString();
		std::string be_adder_school = cm.json_msg_["peer_school"].asString();
		int be_adder_userid = cm.json_msg_["peer_userid"].asInt();

		//刷新好友信息
		struct UserInfo ui;
		ui.nickname_ = be_adder_nickname;
		ui.school_ = be_adder_school;
		ui.userid_ = be_adder_userid;
		ui.msg_cnt_ = 0;
		cw->vec_fri_.push_back(ui);
		//刷新展示区域
		cw->RefreshUserList();
	}
}

BOOL ChatWin::OnInitDialog()
{
	CDialogEx::OnInitDialog();
	std::thread recv_msg(DealPushMsg, this);
	recv_msg.detach();

	std::thread recv_addfriendmsg(DealAddFriendMsg, this);
	recv_addfriendmsg.detach();

	std::thread recv_addfriendrespmsg(DealAddFriendRespMsg, this);
	recv_addfriendrespmsg.detach();
	// TODO:  在此添加额外的初始化
	//1.获取tcp指针
	TcpSvr* ts = TcpSvr::GetInstance();
	if (ts == NULL) {
		MessageBox("获取TCP指针失败,请过一会儿再试");
		return false;
	}
	//2.组织数据
	ChatMsg cm;
	cm.msg_type_ = GetFriendMsg;
	cm.userid_ = uid_;
	std::string msg;
	cm.GetMsg(&msg);
	//3.发送数据
	ts->Send(msg);

	//4.接收应答
	MsgQueue* mq = MsgQueue::GetInstance();
	msg.clear();
	cm.clear();
	mq->Pop(GetFriendMsg_Resp, &msg);
	cm.PraseChatMsg(-1, msg);
	for (int i = 0; i < cm.json_msg_.size(); i++) {
		struct UserInfo ui;
		ui.userid_ = cm.json_msg_[i]["userid"].asInt();
		ui.nickname_ = cm.json_msg_[i]["nickname"].asString();
		ui.school_ = cm.json_msg_[i]["school"].asString();
		vec_fri_.push_back(ui);
		if (i == 0) {
			suid_ = ui.userid_;
		}
	}
	//5.刷新列表
	RefreshUserList();
	return TRUE;  // return TRUE unless you set the focus to a control
				  // 异常: OCX 属性页应返回 FALSE
}

void ChatWin::RefreshUserList() {
	int count = friend_list.GetCount();
	for (int i = count; i >= 0; i--) {
		friend_list.DeleteString(i);
	}
	for (int i = 0; i < (int)vec_fri_.size(); i++) {
		std::string temp = vec_fri_[i].nickname_;
		if (vec_fri_[i].msg_cnt_ > 0) {
			temp += " : ";
			temp += std::to_string(vec_fri_[i].msg_cnt_);
		}
		friend_list.AddString(temp.c_str());
	}
 }


void ChatWin::OnLbnSelchangeListfriendinfo() {
	// TODO: 在此添加控件通知处理程序代码
	//1.获取点击内容
	CString strText;
	int cur = friend_list.GetCurSel();
	friend_list.GetText(cur, strText);

	//2.判断当前是哪个用户,更改发送id
	for (int i = 0; i < vec_fri_.size(); i++) {
		if (strstr(strText, vec_fri_[i].nickname_.c_str()) != NULL) {
			suid_ = vec_fri_[i].userid_;
		}
	} 
	//3.清空展示区域
	int count = msg_list_.GetCount();
	for (int i = count; i >= 0; i--) {
		msg_list_.DeleteString(i);
	}

	//4.显示该用户的历史消息
	for (int i = 0; i < vec_fri_.size(); i++) {
		if (suid_ == vec_fri_[i].userid_) {
			for (size_t k = 0; k < vec_fri_[i].history_msg_.size(); k++) {
				msg_list_.AddString(vec_fri_[i].history_msg_[k].c_str());
			}
		}
		vec_fri_[i].msg_cnt_ = 0;
	}
	//5.刷新好友列表
	RefreshUserList();
}


void ChatWin::OnLbnSelchangeListmsginfo()
{
	// TODO: 在此添加控件通知处理程序代码
	
}


BOOL ChatWin::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) {
		OnBnClickedButsendmsg();
		return TRUE;
	}
	if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_ESCAPE) {
		return TRUE;
	}
	return CDialogEx::PreTranslateMessage(pMsg);
}


void ChatWin::OnBnClickedAddfriend()
{
	// TODO: 在此添加控件通知处理程序代码
	CDialogAddFriend caf(uid_);
	caf.DoModal();
	
}
